//
//  Mix_Helper.m
//  testWebView
//
//  Created by ty804 on 05/04/2019.
//  Copyright © 2019 ty804. All rights reserved.
//

#import "Mix_Helper.h"
#import "Objc_Name.h"
#import "StringHelper.h"
#import "SouceModel.h"
#define FILE_PATH [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingPathComponent:@"fileName"]


static NSString *const MIX_DEFINE_NAME = @"define_";
static NSString *const MIX_INT_NAME = @"int_";
static NSString *const MIX_STRING_NAME = @"string_";
static NSString *const MIX_CLASS_NAME = @"class_";
static NSString *const MIX_FUNCTION_NAME = @"function_";
static NSString *const MIX_PRAMETER_NAME = @"prameter_";
static NSString *const MIX_CONFUSIONCODE = @"confusionCode_";

static NSString *const MIX_FILE_NAME = @"FILE_NAME";

static NSString *const ENCRYPTION_STRING = @"encryption_string";

static NSString *const MIX_REPLACE_NAME = @"MIX_REPLACE_NAME";


@interface Mix_Helper ()
@property (nonatomic,strong)NSArray *arr_class;
@property (nonatomic,strong)NSArray *arr_function;
@property (nonatomic,strong)NSArray *arr_prameter;
@property (nonatomic,strong)NSArray *arr_confusionType;
@end
@implementation Mix_Helper
static Mix_Helper * _instance = nil;
+(Mix_Helper *) sharedManage;{
    @synchronized(self){
        if (_instance == nil) {
            _instance = [[self alloc] init];
            [_instance souce_content];
            [_instance head_souce_content];
            [_instance defautChange];
        }
    }
    return  _instance;
}
-(void)defautChange{
    self.arr_class=@[@"1",@"8",];
    self.arr_function=@[@"37",@"51",@"53",@"52",@"50"];
    self.arr_prameter=@[@"61",@"147",@"158"];
    self.arr_confusionType=@[@"float",@"double",@"BOOL",@"int",@"NSString"];
}
-(NSString*)souce_content{
    NSString *path = [[NSBundle mainBundle] pathForResource:@"Mix_Souce" ofType:@"txt"];
    NSString *content = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    self.strSouce=content;
    return content;
}
-(NSString*)head_souce_content{
    NSString *path = [[NSBundle mainBundle] pathForResource:@"Mix_Head" ofType:@"txt"];
    NSString *content = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    self.strHeadSouce=content;
    return content;
}

-(NSString *)mix_markConfusionname:(NSString *)type nun:(int)num_int{
    
    return [NSString stringWithFormat:@"%@%d",type,num_int];
}

-(void)starMix:(NSDictionary *)dict{
    
    NSString *file_name=[Objc_Name arc4random_class_name];
    self.encryption_string=[Objc_Name arc4random_class_name];
    self.strSouce=[self.strSouce stringByReplacingOccurrencesOfString:MIX_FILE_NAME withString:file_name];
    self.strHeadSouce=[self.strHeadSouce stringByReplacingOccurrencesOfString:MIX_FILE_NAME withString:file_name];
    for (NSString *key in dict.allKeys) {
        NSString *string=[NSString stringWithFormat:@"*%@*%@",self.encryption_string,[dict objectForKey:key]];
       self.strSouce=[self.strSouce stringByReplacingOccurrencesOfString:key withString:string];
    }
    
    NSRange rangeEncryption = [self.strSouce rangeOfString:ENCRYPTION_STRING];
    if (rangeEncryption.location == NSNotFound)
    {
        NSLog(@"没有需要替换的宏变量");
    }else {
        NSString *string=[NSString stringWithFormat:@"*%@*",self.encryption_string];
        self.strSouce=[self.strSouce stringByReplacingOccurrencesOfString:ENCRYPTION_STRING withString:string];
    }
    
    
    //替换宏变量
    NSRange rangeDefine = [self.strSouce rangeOfString:MIX_DEFINE_NAME];
    if (rangeDefine.location == NSNotFound)
    {
        NSLog(@"没有需要替换的宏变量");
    }else {
        for (int i=100; i>=0; i--) {
            NSString *strReplace=[self mix_name:MIX_DEFINE_NAME nun:i];
            self.strSouce=[self.strSouce stringByReplacingOccurrencesOfString:strReplace withString:[Objc_Name arc4random_define_name]];
        }
//        NSLog(@"搜索宏变量范围%@",NSStringFromRange(rangeDefine));
    }
    
    //替换class变量
    NSRange rangeClass = [self.strSouce rangeOfString:MIX_CLASS_NAME];
    if (rangeClass.location == NSNotFound)
    {
        NSLog(@"没有需要替换的class变量");
    }else {
        for (int i=100; i>=0; i--) {
            NSString *strReplace=[self mix_name:MIX_CLASS_NAME nun:i];
            NSString *str=[Objc_Name arc4random_class_name];
            self.strSouce=[self.strSouce stringByReplacingOccurrencesOfString:strReplace withString:str];
            
            for (NSString *str_class in self.arr_class) {
                if (i==str_class.integerValue) {
                    self.strHeadSouce=[self.strHeadSouce stringByReplacingOccurrencesOfString:strReplace withString:str];
                }
            }
        }
//        NSLog(@"搜索class变量范围%@",NSStringFromRange(rangeClass));
    }
    
    //替换function变量
    NSRange rangeFunction= [self.strSouce rangeOfString:MIX_FUNCTION_NAME];
    if (rangeFunction.location == NSNotFound)
    {
        NSLog(@"没有需要替换的PRAMETER变量");
    }else {
        for (int i=100; i>=0; i--) {
            NSString *strReplace=[self mix_name:MIX_FUNCTION_NAME nun:i];
            NSString *str=[Objc_Name arc4random_function_name];
            self.strSouce=[self.strSouce stringByReplacingOccurrencesOfString:strReplace withString:str];
            for (NSString *str_function in self.arr_function) {
                if (i==str_function.integerValue) {
                    self.strHeadSouce=[self.strHeadSouce stringByReplacingOccurrencesOfString:strReplace withString:str];
                }
            }
        }
//        NSLog(@"搜索PRAMETER变量范围%@",NSStringFromRange(rangeFunction));
    }
    
    
    //替换Prameter变量
    NSRange rangePrameter = [self.strSouce rangeOfString:MIX_PRAMETER_NAME];
    if (rangePrameter.location == NSNotFound)
    {
        NSLog(@"没有需要替换的Prameter变量");
    }else {
        for (int i=300; i>=0; i--) {
            NSString *strReplace=[self mix_name:MIX_PRAMETER_NAME nun:i];
            NSString *str=[Objc_Name arc4random_prameter_name];
            self.strSouce=[self.strSouce stringByReplacingOccurrencesOfString:strReplace withString:str];
            for (NSString *str_prameter in self.arr_prameter) {
                if (i==str_prameter.integerValue) {
                    self.strHeadSouce=[self.strHeadSouce stringByReplacingOccurrencesOfString:strReplace withString:str];
                }
            }
        }
//        NSLog(@"搜索Prameter变量范围%@",NSStringFromRange(rangePrameter));
    }
    
    //注入混淆代码
    NSRange rangeConfusionCode = [self.strSouce rangeOfString:MIX_CONFUSIONCODE];
    if (rangePrameter.location == NSNotFound)
    {
        NSLog(@"没有需要替换的ConfusionCode方法");
    }else {
        for (int i=90; i>0; i--) {
            
            //confusionCode_X
            NSString *strConfusionName=[self mix_markConfusionname:MIX_CONFUSIONCODE nun:i];
            NSString * strConfusionStarts = [NSString stringWithFormat:@"%@(",strConfusionName];
            
            NSRange markString = [self.strSouce rangeOfString:strConfusionStarts];
            if (markString.location == NSNotFound)
            {
                NSString * log = [NSString stringWithFormat:@"没有找到替换的ConfusionCode_%d方法",i];
                NSLog(@"%@",log);
            }else{
                
                int injection = arc4random_uniform(5);
                //随机一部分注入代码，一部分不注入
                if(injection){
                    int locationString = @"ConfusionCode_".length;
                    NSString * subMarkString = [self.strSouce substringWithRange:NSMakeRange(markString.location+locationString,30)];
                    
                    //(?<=confusionCode_+\d+\()[^}]*(?=\))
                    NSString *pattern = @"(?<=\\()[^}]*(?=\\))";        //匹配规则
                    NSRegularExpression *regular = [[NSRegularExpression alloc] initWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:nil];
                    
                    
                    NSArray *results = [regular matchesInString:subMarkString options:0 range:NSMakeRange(0, subMarkString.length)];
                    
                    if(results.count >0){
                        NSRange confusionCodeParameterRange = ((NSTextCheckingResult*)results[0]).range;
                        NSString * confusionCodeParameter = [subMarkString substringWithRange:confusionCodeParameterRange];
                        
                        if(confusionCodeParameter != nil){
                            NSString * confusionCodeTemplate = @"";
                            
                            //如果是参数是属性的情况
                            if([confusionCodeParameter hasPrefix:@"self."]){
                                confusionCodeTemplate = [Objc_Name arc4random_confusionCode_template:confusionCodeParameter type:@"int"];
                                NSString * replaceString = [NSString stringWithFormat:@"//%@%@)",strConfusionStarts,confusionCodeParameter];
                                self.strSouce=[self.strSouce stringByReplacingOccurrencesOfString:replaceString withString:confusionCodeTemplate];
                            }else if([confusionCodeParameter hasPrefix:@"*"]){
                                confusionCodeParameter = [confusionCodeParameter stringByReplacingOccurrencesOfString:@"*" withString:@""];
                                confusionCodeTemplate = [Objc_Name arc4random_confusionCode_template:confusionCodeParameter type:@"int"];
                                NSString * replaceString = [NSString stringWithFormat:@"//%@*%@)",strConfusionStarts,confusionCodeParameter];
                                self.strSouce=[self.strSouce stringByReplacingOccurrencesOfString:replaceString withString:confusionCodeTemplate];
                            }else{
                                NSString * type = self.arr_confusionType[arc4random_uniform(self.arr_confusionType.count)];
                                
                                //                                if([type isEqualToString:@"NSString"]){
                                //                                    confusionCodeTemplate = [Objc_Name arc4random_confusionCode_template:confusionCodeParameter type:@"NSString"];
                                //                                }else
                                if([type isEqualToString:@"double"]){
                                    confusionCodeTemplate = [Objc_Name arc4random_confusionCode_template:confusionCodeParameter type:@"double"];
                                }else if([type isEqualToString:@"float"]){
                                    confusionCodeTemplate = [Objc_Name arc4random_confusionCode_template:confusionCodeParameter type:@"float"];
                                }else if([type isEqualToString:@"BOOL"]){
                                    confusionCodeTemplate = [Objc_Name arc4random_confusionCode_template:confusionCodeParameter type:@"BOOL"];
                                }else if([type isEqualToString:@"NSString"]){
                                    confusionCodeTemplate = [Objc_Name arc4random_confusionCode_template:confusionCodeParameter type:@"NSString"];
                                }else{
                                    confusionCodeTemplate = [Objc_Name arc4random_confusionCode_template:confusionCodeParameter type:@"int"];
                                }
                                
                                NSString * replaceString = [NSString stringWithFormat:@"//%@%@)",strConfusionStarts,confusionCodeParameter];
                                if([type isEqualToString:@"NSString"]){
                                    NSString * finalString = [NSString stringWithFormat:@"%@ * %@;%@",type,confusionCodeParameter,confusionCodeTemplate];
                                    self.strSouce=[self.strSouce stringByReplacingOccurrencesOfString:replaceString withString:finalString];
                                }else{
                                    NSString * finalString = [NSString stringWithFormat:@"%@ %@;%@",type,confusionCodeParameter,confusionCodeTemplate];
                                    self.strSouce=[self.strSouce stringByReplacingOccurrencesOfString:replaceString withString:finalString];
                                }
                                
                            }
                            
                        }
                    }else{
                        NSString * log = [NSString stringWithFormat:@"没有找到替换的ConfusionCode_%d()中的参数",i];
                        NSLog(@"%@",log);
                    }
                }else{
                    NSString * log = [NSString stringWithFormat:@"特地没有注入ConfusionCode_%d混淆代码",i];
                    NSLog(@"%@",log);
                    continue;
                }
                
            }
        }
    }
    
    
    
    [self setFunctionAttribut:file_name];

}

-(void)setFunctionAttribut:(NSString *)file_name{
    __block NSMutableArray *arrModel=[NSMutableArray array];
    __block NSArray *classModelT=[NSArray array];
    [[StringHelper sharedManage] traverse_souceCode_souceCode:self.strSouce back:^(NSArray<SouceModel *> * _Nonnull model) {
        [[StringHelper sharedManage]addClassModel:self.classCount totleModel:model back:^(NSArray<SouceModel *> * _Nonnull model, NSArray<ClassModel *> * _Nonnull classmodel) {
            classModelT=classmodel;
            [model enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                
                [[StringHelper sharedManage]addPrameterWithNum:self.index ratio:self.ratio model:obj back:^(SouceModel * _Nonnull model) {
                    [arrModel addObject:model];
                }];
                
            }];
        }];
        
        [[StringHelper sharedManage]addClassPrameter:arrModel classModel:classModelT back:^(NSArray<SouceModel *> * _Nonnull model) {
          
            [[StringHelper sharedManage]restructuringCode:model back:^(NSString * _Nonnull code) {
                 self.strSouce=code;
                 [self writeToFileWithFileName:file_name];
            }];
            
        }];
        
        
    }];
    
    
}


-(NSString *)mix_name:(NSString *)type nun:(int)num_int{
    
    return [NSString stringWithFormat:@"%@%d",type,num_int];
}
-(void)writeToFileWithFileName:(NSString*)fileName{
  
    NSString *h_fileName = [fileName stringByAppendingString:@".h"];
    NSString *h_filePath = [@[FILE_PATH, h_fileName] componentsJoinedByString:@"/"];
    
    NSString *m_fileName = [fileName stringByAppendingString:@".m"];
    NSString *m_filePath = [@[FILE_PATH, m_fileName] componentsJoinedByString:@"/"];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    [fileManager removeItemAtPath:FILE_PATH error:nil];
    BOOL isDir = NO;
    
    BOOL existed = [fileManager fileExistsAtPath:FILE_PATH isDirectory:&isDir];
    if ( !(isDir == YES && existed == YES) ) {
        [fileManager createDirectoryAtPath:FILE_PATH withIntermediateDirectories:YES attributes:nil error:nil];
    }
    
    
    BOOL is_success_write_h_file = [self writeToFile:h_filePath containString:self.strHeadSouce];
    if (!is_success_write_h_file) {
        NSString *error_desc = [NSString stringWithFormat:@"%@.h写入内容失败,请重新生成", fileName];
        NSLog(@"%@",error_desc);
        return;
    }
    
    BOOL is_success_write_m_file = [self writeToFile:m_filePath containString:self.strSouce];
    if (!is_success_write_m_file) {
        NSString *error_desc = [NSString stringWithFormat:@"%@.m写入内容失败,请重新生成", fileName];
        NSLog(@"%@",error_desc);
        return;
    }
  
    NSLog(@"生成成功,路径:%@",FILE_PATH);
    
}
- (BOOL)writeToFile:(NSString *)path containString:(NSString *)containString {
    BOOL isSuccess;
    NSData *data = [containString dataUsingEncoding:NSUTF8StringEncoding];
    isSuccess = [data writeToFile:path atomically:YES];
    return isSuccess;
}
@end
